package person.twj.orderservice.feign.client;

import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import io.seata.core.context.RootContext;
import io.seata.rm.tcc.api.BusinessActionContext;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import person.twj.common.feign.AccountFeignService;
import person.twj.orderservice.entity.OrderFreezeTbl;
import person.twj.orderservice.entity.OrderTbl;
import person.twj.orderservice.service.IOrderFreezeTblService;
import person.twj.orderservice.service.IOrderTblService;

@Service
@Slf4j
public class TccOrderServiceImpl implements TccOrderService{
    @Autowired
    private AccountFeignService accountService;
    @Autowired
    @Qualifier("orderTblServiceImpl")
    private IOrderTblService iOrderTblService;
    @Autowired
    @Qualifier("orderFreezeTblServiceImpl")
    private IOrderFreezeTblService iOrderFreezeTblService;
    @Override
    @Transactional
    public String order(String userId, String commodityCode, int orderCount, int type) {
        log.info("Order Service Begin ... xid: " + RootContext.getXID());

        int orderMoney = calculate(commodityCode, orderCount);


        String rs = accountService.account(userId, orderMoney,type);
        if (!"SUCCESS".equals(rs)) {

            return "FAIL";
        }

        OrderTbl order = OrderTbl.builder()
                .id("1")
                .userId(userId)
                .money(orderMoney)
                .commodityCode(commodityCode)
                .count(orderCount)
                .build();


        OrderTbl oriOrder = iOrderTblService.getById("1");
        log.info("原始order: " + JSON.toJSONString(oriOrder));

        boolean result = iOrderTblService.updateById(order);
        log.info("Order Service End result: " + result);



        if (result) {
            boolean res = iOrderFreezeTblService.save(OrderFreezeTbl.builder()
                    .xid(RootContext.getXID())
                    .orderId(order.getId())
                    .freezeCount(orderCount)
                    .freezeMoney(orderMoney)
                    .status(OrderFreezeTbl.Status.TRY)
                    .build());
            if(res){
                if(type==2){
                    throw new RuntimeException("错误");
                }
                log.info("执行 try 成功");
                return "SUCCESS";
            }

        }
        return "FAIL";
    }

    @Override
    public boolean commit(BusinessActionContext actionContext) {
        log.info("执行 commit 成功");
        return iOrderFreezeTblService.removeById(actionContext.getXid());
    }

    @Override
    public boolean rollback(BusinessActionContext actionContext) {

        OrderFreezeTbl freeze = iOrderFreezeTblService.getById(actionContext.getXid());

        /*if(freeze==null){
            iOrderFreezeTblService.save(OrderFreezeTbl.builder()
                            .status(OrderFreezeTbl.Status.CANSEL)
                            .xid(actionContext.getXid())
                            .freezeCount(0)
                            .orderId(null)
                            .freezeMoney(0)
                    .build());
            return true;
        }*/

        UpdateWrapper wrapper = new UpdateWrapper();
        wrapper.setSql("count = count - {0}"
                +",money = money - {1}"
                +" where id={2}",
                new Object[]{freeze.getFreezeCount(),freeze.getFreezeMoney(),freeze.getOrderId()});



        boolean result = iOrderTblService.update(wrapper);

        if(result){
            freeze.setFreezeMoney(0);
            freeze.setFreezeCount(0);
            freeze.setStatus(OrderFreezeTbl.Status.CANSEL);
            boolean status = iOrderFreezeTblService.updateById(freeze);
            if(status){
                log.info("执行rollback成功");
                return true;
            }
        }

        return false;
    }

    private int calculate(String commodityCode, int orderCount) {
        return orderCount * 100;
    }


}
